home *** CD-ROM | disk | FTP | other *** search
Text File | 1999-03-17 | 10.0 KB | 301 lines | [TEXT/ALFA] |
- ######################################################################
- # #
- # Use at your own risk. This is just a quick-and-dirty RPN stack #
- # calculator, works on both decimal (signed and unsigned), hex #
- # integers, and floating point. I put it #
- # together for my own use, not yours, but feel free to use it as #
- # long as you don't complain about what it doesn't do. #
- # Improvements, of course, are welcome. #
- # #
- # Operations: Top of stack is 'y', next is 'x'. #
- # n bitwise NOT #
- # +,-,*,/,|,&,% Does x OP y. #
- # ^ x eor y or #
- # x^y in floating point mode #
- # < x << y #
- # > x >> y #
- # - <o> insert - sign #
- # - <z> change y's sign #
- # q dup y #
- # i swap x and y #
- # m switch decimal/hex modes #
- # x show current mode #
- # h,? help #
- # <backspace> pop stack #
- # <space> enter number #
- # #
- # Floating point extensions #
- # #
- # f <o> floor(y) #
- # f <so> ceil(y) #
- # #
- # f <z> fmod(x,y) #
- # h <z> hypot(x,y) #
- # p <z> x**y #
- # s <sz> sqrt(y) #
- # #
- # l <z> log(y) #
- # l <sz> exp(y) #
- # l <o> log10(y) #
- # #
- # c <o> cos(y) #
- # s <o> sin(y) #
- # t <o> tan(y) #
- # #
- # c <so> acos(y) #
- # s <so> asin(y) #
- # t <so> atan(y) #
- # #
- # c <z> cosh(y) #
- # s <z> sinh(y) #
- # t <z> tanh(y) #
- # #
- # t <sz> atan2(x,y) #
- # #
- # The mode indicator indicates whether hex or dec is active. #
- # All calculations performed in signed decimal. #
- # #
- ######################################################################
-
- alpha::mode Calc 0.1.2 Calc::dummy {} {} {} \
- help {[editMark [file join $HOME Help "Alpha Manual"] "Calculator" -r -c]}
-
- # Alpha will shift this in and out of global scope as necessary
- newPref variable tcl_precision 17 Calc
-
- proc Calc::dummy {} {}
-
- proc calculator {} {
- global tileLeft tileTop
- if {[set ind [lsearch -exact [winNames] {* Calc *}]] >= 0} {
- bringToFront {* Calc *}
- return
- }
- new -g $tileLeft $tileTop 200 200 -n {* Calc *} -m Calc -shell 1
- }
-
- ascii 0x2b "binop +" Calc
- ascii 0x2d "binop -" Calc
- ascii 0x2a "binop *" Calc
- ascii 0x2f "binop /" Calc
- ascii 0x5e "binop ^" Calc
- ascii 0x26 "binop &" Calc
- ascii 0x25 "binop %" Calc
- ascii 0x3e "binop >>" Calc
- ascii 0x3c "binop <<" Calc
- ascii 0x3f "editMark \"[file join $HOME Help {Alpha Manual}]\" Calculator -r -c" Calc
- ascii 0x68 "editMark \"[file join $HOME Help {Alpha Manual}]\" Calculator -r -c" Calc
- ascii 0x71 calcDup Calc
- ascii 0x69 calcEx Calc
- ascii 0x6d changeCalcMode Calc
- ascii 0x78 "calcShow" Calc
- ascii 0x20 calcEnter Calc
- ascii 0x08 calcDel Calc
- ascii 0x25 "function %" Calc
- ascii 0x5e "function ^" Calc
- Bind '-' <z> "unaryop -" Calc
- Bind '-' <o> { insertText "-" } Calc
- Bind 'l' <os> "binop |" Calc
- Bind 'n' "unaryop ~" Calc
-
- Bind 'f' <o> "unaryop floor" Calc
- Bind 'f' <os> "unaryop ceil" Calc
- Bind 'f' <z> "function fmod" Calc
- Bind 'h' <z> "function hypot" Calc
- Bind 'p' <z> "function pow" Calc
- Bind 's' <sz> "unaryop sqrt" Calc
-
- Bind 'l' <z> "unaryop log" Calc
- Bind 'l' <sz> "unaryop exp" Calc
- Bind 'l' <o> "unaryop log10" Calc
-
- Bind 'c' <o> "unaryop cos" Calc
- Bind 's' <o> "unaryop sin" Calc
- Bind 't' <o> "unaryop tan" Calc
- Bind 'c' <os> "unaryop acos" Calc
- Bind 's' <os> "unaryop asin" Calc
- Bind 't' <os> "unaryop atan" Calc
- Bind 'c' <z> "unaryop cosh" Calc
- Bind 's' <z> "unaryop sinh" Calc
- Bind 't' <z> "unaryop tanh" Calc
- Bind 't' <sz> "function atan2" Calc
-
- Bind 'p' <o> "insertText {3.14159265358979323}" Calc
- Bind 'e' <so> "insertText {2.718281828459045}" Calc
-
- set calcMode 3
-
- proc changeCalcMode {} {
- global calcMode
-
- goto [maxPos]
- if {[pos::compare [getPos] > [minPos]]} {
- if {[lookAt [pos::math [getPos] - 1]] != "\r"} calcEnter
- set nums {}
- set t ""
- foreach n [split [getText [minPos] [pos::math [maxPos] - 1]] "\r"] {
- lappend nums [calcGet $n]
- }
- set calcMode [expr {($calcMode + 1) % 4}]
- foreach n $nums {
- append t "[calcPut $n]\r"
- }
- replaceText [minPos] [maxPos] $t
- } else {
- set calcMode [expr {($calcMode + 1) % 4}]
- }
- switch -- "$calcMode" {
- 0 {message "Signed decimal" }
- 1 {message "Unsigned decimal"}
- 2 {message "Unsigned hexadecimal"}
- 3 {message "Floating Point"}
- }
- }
-
-
- proc calcShow {} {
- global calcMode
- switch -- "$calcMode" {
- 0 {message "Signed decimal" }
- 1 {message "Unsigned decimal"}
- 2 {message "Unsigned hexadecimal"}
- 3 {message "Floating Point"}
- }
- }
-
-
- proc calcGet {in} {
- global calcMode
-
- switch -- "$calcMode" {
- 0 {scan $in "%d" num; return $num}
- 1 {scan $in "%u" num; return $num}
- 2 {scan $in "%x" num; return $num}
- 3 {scan $in "%g" num; return $num}
- }
- error "Bad hex num '$in'"
- }
-
- proc calcPut {in} {
- global calcMode
-
- if {$calcMode != 3} {
- regexp {[0-9-]+} $in in
- }
- switch -- $calcMode {
- 0 {return [format "%10d" $in]}
- 1 {return [format "%10u" $in]}
- 2 {return [format "%10x" $in]}
- 3 {return [format "%17.6f" $in]}
- }
- }
-
-
- proc binop {op} {
- global calcMode
- if {$calcMode == 3 && ($op == "&" || $op == "|" \
- || $op == "<<" || $op == ">>")} {
- beep
- message "${op} does not work in floating point mode"
- return
- }
- goto [maxPos]
- if {[lookAt [pos::math [getPos] - 1]] != "\r"} calcEnter
- set pos [lineStart [getPos]]
- set st_y [lineStart [pos::math $pos - 1]]
- set st_x [lineStart [pos::math $st_y - 1]]
- if {[pos::compare $st_y == $st_x]} { beep; return}
- set res [eval expr {[calcGet [getText $st_x $st_y]] $op \
- [calcGet [getText $st_y $pos]]}]
- replaceText $st_x [maxPos] [calcPut $res] "\r"
- }
-
- proc unaryop {op} {
- global calcMode
- if {$calcMode != 3 && $op != "-" && $op != "~"} {
- beep
- message "${op} works only in floating point mode"
- return
- }
- goto [maxPos]
-
- set pos [getPos]
- set last [lineStart [pos::math [getPos] - 1]]
- set res [eval expr "${op}([calcGet [getText $last $pos]])"]
- replaceText $last $pos [calcPut $res] "\r"
- }
-
- proc function {op} {
- global calcMode
- if {$calcMode != 3} {
- if { $op == "^" || $op == "%"} {
- binop $op
- return
- }
- beep
- message "${op} works only in floating point mode"
- return
- }
- if { $op == "^" } {set op "pow"}
- if { $op == "%" } {set op "fmod"}
- goto [maxPos]
- if {[lookAt [pos::math [getPos] - 1]] != "\r"} calcEnter
- set pos [lineStart [getPos]]
- set st_y [lineStart [pos::math $pos - 1]]
- set st_x [lineStart [pos::math $st_y - 1]]
- if {[pos::compare $st_y == $st_x]} { beep; return}
- set res [eval expr "${op}([calcGet [getText $st_x $st_y]],\
- [calcGet [getText $st_y $pos]])"]
- replaceText $st_x [maxPos] "[calcPut $res]\r"
- }
-
- proc calcEx {} {
- goto [maxPos]
- if {[lookAt [pos::math [getPos] - 1]] != "\r"} calcEnter
- set pos [lineStart [getPos]]
- set st_y [lineStart [pos::math $pos - 1]]
- set st_x [lineStart [pos::math $st_y - 1]]
- if {[pos::compare $st_y == $st_x]} { beep; return}
- replaceText $st_x [maxPos] "[getText $st_y $pos][getText $st_x $st_y]"
- }
-
-
- proc calcEnter {} {
- global calcMode
- goto [maxPos]
- switch -- "$calcMode" {
- 0 {set ex {[0-9-]+$}}
- 1 {set ex {[0-9]+$}}
- 2 {set ex {[0-9a-f]+$}}
- 3 {set ex {[eE0-9.-]+$}}
- }
- if {[regexp -- $ex [getText [lineStart [getPos]] [getPos]] num]} {
- set num [calcGet $num]
- replaceText [lineStart [getPos]] [getPos] [calcPut $num] "\r"
- } else {
- beep
- beginningOfLine
- killLine
- }
- }
-
- proc calcDel {} {
- goto [maxPos]
- if {[lookAt [pos::math [getPos] - 1]] == "\r"} {
- deleteText [lineStart [pos::math [getPos] - 1]] [getPos]
- } else {
- backSpace
- }
- }
-
- proc calcDup {} {
- goto [maxPos]
- if {[lookAt [pos::math [getPos] - 1]] != "\r"} calcEnter
- set to [lineStart [getPos]]
- set from [lineStart [pos::math $to - 1]]
- set t [getText $from $to]
- insertText $t
- }
-
-
-